﻿Imports System.Drawing.Printing
Imports System.Xml

Namespace Objects

    ''' <summary>
    ''' Abstracte klasse om verkopen af te printen.
    ''' Wordt geïmplementeerd in PrintTicketDocument, PrintKasbladDocument en PrintLeveringsbonDocument
    ''' </summary>
    Public MustInherit Class PrintVerkoopDocument
        Inherits PrintFairShopDocument

        Protected _naamWinkelier As String
        Protected _datum As DateTime
        Protected _totaalBedrag As Decimal
        Protected _details As List(Of VerkoopsPrintDetail)

        Protected _verkoop As ArtikelsDataSet.VerkopenRow

#Region "Public property's"

        Protected Overrides ReadOnly Property DetailCount() As Integer
            Get
                Return _details.Count()
            End Get
        End Property

        Protected Overridable ReadOnly Property SortOrder() As Objects.SortOrder
            Get
                Return Objects.SortOrder.Chronologisch
            End Get
        End Property

#End Region

#Region "Constructor/Initialisatie"

        Public Sub New(ByVal verkoop As ArtikelsDataSet.VerkopenRow)
            MyBase.New()
            _verkoop = verkoop

            Dim details As New List(Of VerkoopsDetail)
            Dim totaalBedrag As Decimal = 0D

            Dim sortString As String = ""
            Select Case Me.SortOrder
                Case Objects.SortOrder.Chronologisch ' voor kasbladen en leveringsbonnen cash betaald
                    sortString = "VolgnummerKlant ASC, Id ASC"
                Case Objects.SortOrder.PerArtikel
                    sortString = "VolgnummerKlant ASC, IdArtikel ASC" ' voor leveringsbonnen nog niet betaald
            End Select
            ' zorg ervoor dat de details gesorteerd zijn op volgnummerklant en id
            Dim verkoopsDetailsTabel As ArtikelsDataSet.VerkoopsDetailsDataTable = DirectCast(verkoop.Table.DataSet, ArtikelsDataSet).VerkoopsDetails
            Dim dv As New DataView(verkoopsDetailsTabel, "IdVerkoop=" & verkoop.Id, sortString, DataViewRowState.CurrentRows)

            For Each drv As DataRowView In dv
                Dim detailRij As ArtikelsDataSet.VerkoopsDetailsRow = DirectCast(drv.Row, ArtikelsDataSet.VerkoopsDetailsRow)
                Dim detail As New VerkoopsDetail(detailRij)
                details.Add(detail)
                totaalBedrag += (detail.TotaalPrijsZonderStatiegeld + detail.TotaalAfTeDrukkenStatiegeld)
            Next

            Dim winkelier As String = verkoop.WinkeliersRow.Naam
            Initialize(details, winkelier, totaalBedrag)
        End Sub

        Public Sub New(ByVal details As List(Of VerkoopsDetail), ByVal winkelier As String, ByVal totaalBedrag As Decimal)
            MyBase.New()
            Initialize(details, winkelier, totaalBedrag)
        End Sub

        ''' <summary>
        ''' 
        ''' </summary>
        ''' <param name="details">Lijst van verkoopsdetails die op het document moeten komen.
        ''' Bij een ticket zijn dat alleen de details van de huidige klant.</param>
        ''' <param name="winkelier"></param>
        ''' <param name="totaalBedrag"></param>
        Private Sub Initialize(ByVal details As List(Of VerkoopsDetail), ByVal winkelier As String, ByVal totaalBedrag As Decimal)
            _naamWinkelier = winkelier
            _datum = DateTime.Now()
            _totaalBedrag = totaalBedrag

            Dim vorigeVolgnummerKlant As String = ""

            _details = New List(Of VerkoopsPrintDetail)
            For Each detail As VerkoopsDetail In details
                Dim volgnummerKlant As String = detail.VolgnummerKlant.ToString()
                If (volgnummerKlant = vorigeVolgnummerKlant) Then volgnummerKlant = ""
                _details.Add(GetVerkoopsPrintDetail(detail, volgnummerKlant))
                vorigeVolgnummerKlant = detail.VolgnummerKlant.ToString()
            Next
            InitializePrinter()
        End Sub

#End Region

#Region "MustOverride"

        ''' <summary>
        ''' Implementeert het factory-pattern
        ''' </summary>
        ''' <param name="detail"></param>
        ''' <param name="volgnummerKlant"></param>
        ''' <returns></returns>
        Protected MustOverride Function GetVerkoopsPrintDetail(ByVal detail As VerkoopsDetail, ByVal volgnummerKlant As String) As VerkoopsPrintDetail

#End Region

#Region "Protected en public methods"

        Protected Overloads Overrides Sub OnBeginPrint(ByVal e As PrintEventArgs)
            MyBase.OnBeginPrint(e)
            InitializeFont()
            _indexVolgendAfTeDrukkenDetail = 0
        End Sub

        Protected Overloads Overrides Sub OnEndPrint(ByVal e As PrintEventArgs)
            MyBase.OnEndPrint(e)
            _font.Dispose()
        End Sub

        Protected Overrides Function PrintDetails(ByVal top As Integer) As Integer
            ' print kolomtitels voor detail
            Dim detailBlok As DocumentBlok = GetBlok("detail")
            If (detailBlok.TitelRij IsNot Nothing) Then
                top = detailBlok.TitelRij.Print(top, _gdiPage)
            End If

            While _indexVolgendAfTeDrukkenDetail < DetailCount
                Dim detail As VerkoopsPrintDetail = _details(_indexVolgendAfTeDrukkenDetail)
                top = detail.Print(detailBlok.SjabloonRij, top)
                _indexVolgendAfTeDrukkenDetail += 1
                If (IsPaginaBeperkt() AndAlso (top + _font.Height > PrintableHeight)) Then Exit While
            End While
            Return top
        End Function

        ''' <summary>
        ''' Print een blok met btw-totalen af.
        ''' Wordt gebruikt in kasbladen en leveringsbonnen.
        ''' </summary>
        ''' <param name="top">Bovenkantpositie vanaf waar geprint moet worden</param>
        ''' <returns>Verticale positie van de volgende regel op het blad</returns>
        Protected Function PrintBtwBlok(ByVal top As Integer) As Integer
            Dim btwBlok As DocumentBlok = GetBlok("btw")

            top = btwBlok.TitelRij.Print(top, _gdiPage)

            Dim btwTotalen As BtwTotalen = GetBtwTotalen()
            For Each btwTotaal As BtwTotaal In btwTotalen.Values
                If (btwTotaal.Btw = 0D) Then
                    If (btwTotalen.TotaalLeeggoed = 0 AndAlso btwTotalen.TotaalCheques = 0 AndAlso btwTotaal.TotaalZonderBtw = 0) Then
                        ' niets afdrukken als alle delen 0 zijn
                        Continue For
                    End If
                    ' voor 0% BTW uitsplitsen
                    btwBlok.SjabloonRij.SetCelTekst("zonderbtw", btwTotalen.TotaalLeeggoed.ToString("c"))
                    btwBlok.SjabloonRij.SetCelTekst("percentage", "0 % - Leeggoed")
                    btwBlok.SjabloonRij.SetCelTekst("btw", 0.ToString("c"))
                    btwBlok.SjabloonRij.SetCelTekst("totaal", btwTotalen.TotaalLeeggoed.ToString("c"))
                    top = btwBlok.SjabloonRij.Print(top, _gdiPage)
                    btwBlok.SjabloonRij.SetCelTekst("zonderbtw", btwTotalen.TotaalCheques.ToString("c"))
                    btwBlok.SjabloonRij.SetCelTekst("percentage", "0 % - Cheques")
                    btwBlok.SjabloonRij.SetCelTekst("btw", 0.ToString("c"))
                    btwBlok.SjabloonRij.SetCelTekst("totaal", btwTotalen.TotaalCheques.ToString("c"))
                    top = btwBlok.SjabloonRij.Print(top, _gdiPage)
                    Dim rest As Decimal = btwTotaal.TotaalZonderBtw - btwTotalen.TotaalLeeggoedEnCheques
                    btwBlok.SjabloonRij.SetCelTekst("zonderbtw", rest.ToString("c"))
                    btwBlok.SjabloonRij.SetCelTekst("percentage", "0 % - Rest")
                    btwBlok.SjabloonRij.SetCelTekst("btw", 0.ToString("c"))
                    btwBlok.SjabloonRij.SetCelTekst("totaal", rest.ToString("c"))
                    top = btwBlok.SjabloonRij.Print(top, _gdiPage)
                    btwBlok.SjabloonRij.SetCelTekst("zonderbtw", btwTotaal.TotaalZonderBtw.ToString("c"))
                    btwBlok.SjabloonRij.SetCelTekst("percentage", "0 % - Totaal")
                    btwBlok.SjabloonRij.SetCelTekst("btw", 0.ToString("c"))
                    btwBlok.SjabloonRij.SetCelTekst("totaal", btwTotaal.TotaalMetBtw.ToString("c"))
                    top = btwBlok.SjabloonRij.Print(top, _gdiPage)
                Else
                    btwBlok.SjabloonRij.SetCelTekst("zonderbtw", btwTotaal.TotaalZonderBtw.ToString("c"))
                    btwBlok.SjabloonRij.SetCelTekst("percentage", String.Format("{0} %", btwTotaal.BtwPercentage))
                    btwBlok.SjabloonRij.SetCelTekst("btw", btwTotaal.Btw.ToString("c"))
                    btwBlok.SjabloonRij.SetCelTekst("totaal", btwTotaal.TotaalMetBtw.ToString("c"))
                    top = btwBlok.SjabloonRij.Print(top, _gdiPage)
                End If
            Next

            ' Te betalen
            btwBlok.SjabloonRij.SetCelTekst("zonderbtw", "")
            btwBlok.SjabloonRij.SetCelTekst("percentage", "Totaal")
            btwBlok.SjabloonRij.SetCelTekst("btw", "")
            btwBlok.SjabloonRij.SetCelTekst("totaal", btwTotalen.TotaalMetLeeggoedEnCheques.ToString("c"))
            top = btwBlok.SjabloonRij.Print(top, _gdiPage)

            Return top
        End Function

        Protected Function GetBtwTotalen() As BtwTotalen
            Dim btwTotalen As New BtwTotalen()
            'For Each detailPrint As VerkoopsPrintDetail In _details
            For i As Integer = 0 To Me.DetailCount - 1
                Dim detailPrint As VerkoopsPrintDetail = _details(i)
                Dim detail As VerkoopsDetail = detailPrint.VerkoopsDetail
                btwTotalen.VoegDetailToe(detail)
                'btwTotalen.VoegToeAanTotaal(detail.BTW, detail.TotaalPrijsZonderStatiegeld)
                'If (detail.TotaalAfTeDrukkenStatiegeld <> 0) Then
                '    ' leeggoed nog boeken onder 0% BTW
                '    btwTotalen.VoegToeAanTotaal(0S, detail.TotaalAfTeDrukkenStatiegeld)
                'End If
            Next
            Return btwTotalen
        End Function

        Protected Overrides Function ShouldPrintPageNumber() As Boolean
            Return True
        End Function

#End Region

#Region "Private methods"

        Private Sub InitializeFont()
            Dim fontNode As XmlNode = _doc.SelectSingleNode("//document/@font")
            Dim fontSizeNode As XmlNode = _doc.SelectSingleNode("//document/@fontsize")
            _font = New Font(fontNode.Value, Convert.ToSingle(fontSizeNode.Value))
        End Sub

#End Region

#Region "Helper classes"

        Protected MustInherit Class VerkoopsPrintDetail

            Protected _verkoopsDetail As VerkoopsDetail
            Protected _document As PrintVerkoopDocument
            Protected _volgnummerKlant As String

            Public ReadOnly Property VerkoopsDetail() As VerkoopsDetail
                Get
                    Return _verkoopsDetail
                End Get
            End Property

            Public Sub New(ByVal verkoopsDetail As VerkoopsDetail, ByVal document As PrintVerkoopDocument, ByVal volgnummerKlant As String)
                _verkoopsDetail = verkoopsDetail
                _document = document
                _volgnummerKlant = volgnummerKlant
            End Sub

            ''' <summary>
            ''' Methode die één detailrij van de verkoop afdrukt.
            ''' Wordt overschreven in de afgeleide klasse naargelang het type afdruk
            ''' </summary>
            ''' <param name="sjabloonRij"></param>
            ''' <param name="top">Bovenkant vanaf waar geprint moet worden</param>
            ''' <returns>Bovenkant-positie van de volgende rij in dpi</returns>
            Public MustOverride Function Print(ByVal sjabloonRij As DocumentRij, ByVal top As Integer) As Integer

        End Class

#End Region

    End Class

    Public Enum SortOrder
        Chronologisch
        PerArtikel
    End Enum

End Namespace
